﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml.Linq;
using System.Windows.Forms;

namespace WorldEditor
{
    public partial class Form1 : Form
    {
        
        Bitmap tSet;

        selection[,] map = new selection[5, 5];

        Size mapSize = new Size(5, 5);
        Size tSetSize = new Size(4, 2);
        Size tSize = new Size(32, 32);

        Point selectedT = new Point(0, 0);

        ResizeImage pSize;

        bool way_point_active = false;
        bool Tile_draw_active = false;

        List<Region> Reg = new List<Region>();

        int selectedIndex = -1;

        string filePath;

        public struct selection
        {
            Point slMap;
            public System.Drawing.Point SlMap
            {
                get { return slMap; }
                set { slMap = value; }
            }
            int slMindex;
            public int SlMindex
            {
                get { return slMindex; }
                set { slMindex = value; }
            }
        }

        public Form1()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            FolderBrowserDialog browser = new FolderBrowserDialog();
            if (DialogResult.OK == browser.ShowDialog())
            {
                filePath = browser.SelectedPath;
            }
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = filePath;
            if (DialogResult.OK == dlg.ShowDialog())
            {
                tSet = new Bitmap(dlg.FileName);
            }
            bufferPanel12.AutoScroll = true;
            bufferPanel12.AutoScrollMinSize = new Size(mapSize.Width * tSize.Width
                                                                , mapSize.Height * tSize.Height);

            panel1.AutoScroll = true;
            panel1.AutoScrollMinSize = new Size(tSet.Width * tSize.Width
                                                                , tSet.Height * tSize.Height);
            pSize = new ResizeImage(mapSize, tSize, tSetSize, tSet, "default.bmp");
            listBoxTileSet.Items.Add(pSize);
            listBoxTileSet.SelectedIndex = 0;
        }

        void Settings_Apply(object sender, OptionBox.ApplyEventArgs e)
        {
            mapSize = new Size(e.reSize.MSize.Width, e.reSize.MSize.Height);
            map = new selection[e.reSize.MSize.Width, e.reSize.MSize.Height];
            tSize = new Size(e.reSize.TSize.Width, e.reSize.TSize.Height);
            tSetSize = new Size(e.reSize.TSetSize.Width, e.reSize.TSetSize.Height);
            bufferPanel12.AutoScrollMinSize = new Size(mapSize.Width * tSize.Width
                                                                , mapSize.Height * tSize.Height);
            panel1.AutoScrollMinSize = new Size(tSet.Width * tSize.Width
                                                                , tSet.Height * tSize.Height);
            bufferPanel12.Invalidate();
            panel1.Invalidate();
        }

        private void bufferPanel12_Paint_1(object sender, PaintEventArgs e)
        {

            if (Tile_draw_active = true)
            {
                for (int x = 0; x < mapSize.Width; ++x)
                {
                    for (int y = 0; y < mapSize.Height; ++y)
                    {
                        Rectangle dRect = Rectangle.Empty;
                        dRect.X = x * tSize.Width;
                        dRect.Y = y * tSize.Height;
                        dRect.X += bufferPanel12.AutoScrollPosition.X;
                        dRect.Y += bufferPanel12.AutoScrollPosition.Y;
                        dRect.Size = tSize;

                        Rectangle sRect = Rectangle.Empty;
                        sRect.X = map[x, y].SlMap.X * tSize.Width;
                        sRect.Y = map[x, y].SlMap.Y * tSize.Height;
                        sRect.Size = tSize;

                        ResizeImage Resize = ((ResizeImage)listBoxTileSet.Items[map[x, y].SlMindex]);

                        e.Graphics.DrawImage(Resize.TMap, dRect, sRect, GraphicsUnit.Pixel);

                        e.Graphics.DrawRectangle(Pens.Black, dRect);

                    }
                }
            }
            if (way_point_active == true)
            {
                for (int i = 0; i < Reg.Count; ++i)
                {
                    Graphics g = e.Graphics;

                    Brush b = new SolidBrush(Color.Red);

                    Pen p = new Pen(Color.Black);

                    p.Width = .25f;

                    Rectangle rect = new Rectangle(Reg[i].Location.X, Reg[i].Location.Y, 32, 32);


                    g.DrawRectangle(p, rect);

                    if (i == selectedIndex)
                    {

                        p = new Pen(Color.Red, 4f);

                        g.DrawRectangle(p, rect);
                    }
                    if (i > 0)
                    {
                        Point a = new Point();
                        Point c = new Point();

                        int temp = i - 1;

                        a.X = Reg[temp].Location.X + 16;
                        a.Y = Reg[temp].Location.Y + 16;
                        c.X = Reg[i].Location.X + 16;
                        c.Y = Reg[i].Location.Y + 16;

                        g.DrawLine(Pens.Black, a, c);

                    }

                    TextRenderer.DrawText(g, Reg[i].Name, new Font("Arial", 12), rect, Color.Black, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
                }
            }

        }

        private void bufferPanel12_MouseClick(object sender, MouseEventArgs e)
        {
            int x = (e.X - bufferPanel12.AutoScrollPosition.X) / tSize.Width;
            int y = (e.Y - bufferPanel12.AutoScrollPosition.Y) / tSize.Height;

            map[x, y].SlMap = selectedT;
            map[x, y].SlMindex = listBoxTileSet.SelectedIndex;
            bufferPanel12.Invalidate();
        }

        private void bufferPanel12_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                int x = (e.X - bufferPanel12.AutoScrollPosition.X);
                int y = (e.Y - bufferPanel12.AutoScrollPosition.Y);

                if (x < tSize.Width * mapSize.Width && y < tSize.Height * mapSize.Height)
                {

                    if (x > 0 && y > 0)
                    {
                        int y1 = y / tSize.Height;
                        int x1 = x / tSize.Width;

                        map[x1, y1].SlMap = selectedT;
                        map[x1, y1].SlMindex = listBoxTileSet.SelectedIndex;

                        bufferPanel12.Invalidate();
                    }
                }

            }
        }

        private void bufferPanel12_Scroll(object sender, ScrollEventArgs e)
        {
            bufferPanel12.Invalidate();

        }

        private void button6_Click(object sender, EventArgs e)
        {
            
            OptionBox Settings = new OptionBox();


            Settings.Apply += new OptionBox.ApplyEventHandler(Settings_Apply);
            if (DialogResult.OK == Settings.ShowDialog())
            {
                mapSize = new Size(Settings.rSize.MSize.Width, Settings.rSize.MSize.Height);
                map = new selection[Settings.rSize.MSize.Width, Settings.rSize.MSize.Height];
                tSize = new Size(Settings.rSize.TSize.Width, Settings.rSize.TSize.Height);
                tSetSize = new Size(Settings.rSize.TSetSize.Width, Settings.rSize.TSetSize.Height);
                string name = Settings.rSize.Name;
                ResizeImage rSize = new ResizeImage(mapSize, tSize, tSetSize, new Bitmap(name), name);
                bufferPanel12.AutoScrollMinSize = new Size(mapSize.Width * tSize.Width
                                                                    , mapSize.Height * tSize.Height);
                panel1.AutoScrollMinSize = new Size(tSet.Width * tSize.Width
                                                                    , tSet.Height * tSize.Height);
                listBoxTileSet.Items.Add(rSize);
                bufferPanel12.Invalidate();
                panel1.Invalidate();
            }

        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            ResizeImage rSize = ((ResizeImage)listBoxTileSet.Items[listBoxTileSet.SelectedIndex]);
            e.Graphics.DrawImage(rSize.TMap, new Rectangle(new Point(panel1.AutoScrollPosition.X, panel1.AutoScrollPosition.Y), new Size(rSize.TMap.Width, rSize.TMap.Height))
                , new Rectangle(new Point(), new Size(rSize.TMap.Width, rSize.TMap.Height)), GraphicsUnit.Pixel);

            Rectangle tRect = Rectangle.Empty;

            for (int x = 0; x < rSize.tSetSize.Width; ++x)
            {
                for (int y = 0; y < rSize.tSetSize.Height; ++y)
                {

                    tRect.X = x * rSize.tSize.Width + panel1.AutoScrollPosition.X;
                    tRect.Y = y * rSize.tSize.Height + panel1.AutoScrollPosition.Y;
                    tRect.Size = rSize.tSize;

                    e.Graphics.DrawRectangle(Pens.Black, tRect);
                }
            }
            tRect.X = selectedT.X * rSize.tSize.Width + panel1.AutoScrollPosition.X;
            tRect.Y = selectedT.Y * rSize.tSize.Height + panel1.AutoScrollPosition.Y;
            tRect.Size = rSize.tSize;

            Pen p = new Pen(Color.Red, 4f);
            e.Graphics.DrawRectangle(p, tRect);
        }

        private void listBoxTileSet_SelectedIndexChanged(object sender, EventArgs e)
        {
            panel1.Invalidate();

        }

        private void panel1_MouseClick(object sender, MouseEventArgs e)
        {
            ResizeImage rSize = ((ResizeImage)listBoxTileSet.Items[listBoxTileSet.SelectedIndex]);

            selectedT.X = (e.X - panel1.AutoScrollPosition.X) / rSize.tSize.Width;
            selectedT.Y = (e.Y - panel1.AutoScrollPosition.Y) / rSize.tSize.Height;
            panel1.Invalidate();
        }

        private void panel1_Scroll(object sender, ScrollEventArgs e)
        {
            panel1.Invalidate();
        }

        private void optionsToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            OptionBox Settings = new OptionBox();


            Settings.Apply += new OptionBox.ApplyEventHandler(Settings_Apply);
            if (DialogResult.OK == Settings.ShowDialog())
            {
                mapSize = new Size(Settings.rSize.MSize.Width, Settings.rSize.MSize.Height);
                map = new selection[Settings.rSize.MSize.Width, Settings.rSize.MSize.Height];
                tSize = new Size(Settings.rSize.TSize.Width, Settings.rSize.TSize.Height);
                tSetSize = new Size(Settings.rSize.TSetSize.Width, Settings.rSize.TSetSize.Height);
                bufferPanel12.AutoScrollMinSize = new Size(mapSize.Width * tSize.Width
                                                                    , mapSize.Height * tSize.Height);
                panel1.AutoScrollMinSize = new Size(tSet.Width * tSize.Width
                                                                    , tSet.Height * tSize.Height);
                bufferPanel12.Invalidate();
                panel1.Invalidate();
            }

        }
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();

            dlg.Filter = "All Files|*.*|Xml Files|*.xml";

            dlg.DefaultExt = "xml";


            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement CurMap = new XElement("map");
                XElement tileImages = new XElement("Images");
                XElement TileSize = new XElement("TileSize");
                XElement xtile = new XElement("Tiles");
                XAttribute xTWidth = new XAttribute("Width", tSize.Width.ToString());
                XAttribute xTHeight = new XAttribute("Height",tSize.Height.ToString());
                XAttribute xMWidth = new   XAttribute("Width", mapSize.Width.ToString());
                XAttribute xMHeight = new XAttribute("Height", mapSize.Height.ToString());
                TileSize.Add(xTWidth);
                TileSize.Add(xTHeight);
                CurMap.Add(xMWidth);
                CurMap.Add(xMHeight);
                CurMap.Add(TileSize);

                for (int i = 0; i < listBoxTileSet.Items.Count; ++i)
                {
                    ResizeImage fuckU = ((ResizeImage)listBoxTileSet.Items[i]);


                    XElement currImage = new XElement("Image", fuckU.Name);
                    tileImages.Add(currImage);

                }
                CurMap.Add(tileImages);

                for (int x = 0; x < mapSize.Width; ++x)
                {
                    for (int y = 0; y < mapSize.Height; ++y)
                    {
                        XElement curtile = new XElement("Tile");
                        
                        object[] mapArray = new object[3];
                        mapArray[0] = map[x, y].SlMap.X.ToString();
                        mapArray[1] = map[x, y].SlMap.Y.ToString();
                        mapArray[2] = map[x, y].SlMindex.ToString();
                        
                        XAttribute tileX = new XAttribute("tileX", mapArray[0]);
                        curtile.Add(tileX);
                        XAttribute tileY = new XAttribute("tileY", mapArray[1]);
                        curtile.Add(tileY);
                        XAttribute tileIndex = new XAttribute("tileIndex", mapArray[2]);
                        curtile.Add(tileIndex);
                        xtile.Add(curtile);
                    }
                }
                CurMap.Add(xtile);
                CurMap.Save(dlg.FileName);
            }
        }

        private void loadMapToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                listBoxTileSet.Items.Clear();

                XElement xRoot = XElement.Load(dlg.FileName);

                //XElement xMapSize = xRoot.Element("map");
                mapSize = new Size(int.Parse(xRoot.Attribute("Width").Value), int.Parse(xRoot.Attribute("Height").Value));
                XElement xTSize = xRoot.Element("TileSize");
                tSize = new Size(int.Parse(xTSize.Attribute("Width").Value), int.Parse(xTSize.Attribute("Height").Value));
                XElement xImages = xRoot.Element("Images");
                IEnumerable<XElement> xImage = xImages.Elements();


                foreach (XElement xIel in xImage)
                {
                    ResizeImage n = new ResizeImage(mapSize, tSize, tSetSize, new Bitmap(xIel.Value), xIel.Value);

                    listBoxTileSet.Items.Add(n);
                }
                map = new selection[mapSize.Width, mapSize.Height];
                XElement xTiles = xRoot.Element("Tiles");
                IEnumerable<XElement> xTile = xTiles.Elements();
                int r = 0;
                int c = 0;
                foreach (XElement xTel in xTile)
                {
                    selection n = new selection();
                    XAttribute x = xTel.Attribute("tileX");
                    XAttribute y = xTel.Attribute("tileY");
                    XAttribute tileIndex = xTel.Attribute("tileIndex");

                    n.SlMap = new Point(int.Parse(x.Value), int.Parse(y.Value));
                    n.SlMindex = int.Parse(tileIndex.Value);

                    map[r, c] = n;
                    c++;
                    if (c == mapSize.Width)
                    {
                        c = 0;
                        r++;
                    }
                }
                listBoxTileSet.SelectedIndex = listBoxTileSet.Items.Count - 1;
                bufferPanel12.AutoScrollMinSize = new Size(mapSize.Width * tSize.Width
                                                                   , mapSize.Height * tSize.Height);
                bufferPanel12.Invalidate();
                panel1.Invalidate();
            }

        }

        
                     public event EventHandler addWayPoint;

                    
                     public Region RegEdit
                     {
                         get
                         {
                             Region wp = new Region();

                             wp.Name = textBoxSelectdT.Text;

                             Point p = Point.Empty;

                             p.X = (int)numericUpDownx.Value;
                             p.Y = (int)numericUpDowny.Value;


                             wp.Location = p;

                             return wp;
                         }
                         set
                         {
                             textBoxSelectdT.Text = value.Name;
                             numericUpDownx.Value = value.Location.X;
                             numericUpDowny.Value = value.Location.Y;
                         }
                     }


                    private void button8_Click(object sender, EventArgs e)
                    {
                         if (addWayPoint != null)
                         {
                             addWayPoint(this, EventArgs.Empty);
                         }
        
                    }

                    private void bufferPanel12_MouseDoubleClick(object sender, MouseEventArgs e)
                    {


                        Region r = new Region();

                        Point l = new Point();

                        r.name = "Unknown";

                        l.X = (int)e.X - 16;
                        l.Y = (int)e.Y - 16;

                        r.Location = l;
                        Reg.Add(r);
                        listBoxWayPoint.Items.Add(r);
                        panel1.Invalidate();
                    }

                    private void tabPage3_Enter(object sender, EventArgs e)
                    {
                        way_point_active = true;
                    }

                    private void tabPage3_Leave(object sender, EventArgs e)
                    {
                        way_point_active = false;
                    }

                    private void tabPage1_Leave(object sender, EventArgs e)
                    {
                        Tile_draw_active = false;
                    }

                    private void tabPage1_Enter(object sender, EventArgs e)
                    {
                        Tile_draw_active = true;
                    }


        } 
}
